<!-- 渠成自定义通用CRUD页面，提供指定表数据的CRUD操作 -->
<template>
  <div>
    <BasicTable
      @register="registerTable"
      size="small"
      :can-resize="true"
      :bordered="true"
      :striped="true"
      :loading="false"
      :title="moduleTitle"
      :columns="tableColumns"
      :data-source="tableData"
    >
      <template #toolbar>
        <a-button type="success" size="small" @click="onAddButtonClick()"
          ><PlusOutlined />录入数据</a-button
        >
      </template>

      <template #action="{ record }">
        <TableAction
          :actions="[
            {
              icon: 'clarity:note-edit-line',
              label: '修改',
              onClick: onEditButtonClick.bind(null, record),
            },
            {
              icon: 'ant-design:delete-outlined',
              label: '删除',
              color: 'error',
              popConfirm: {
                title: '是否确认删除',
                confirm: onDeleteButtonClick.bind(null, record),
              },
            },
          ]"
        />
      </template>
    </BasicTable>
    <!-- 新增或修改弹窗组件 -->
    <CrudEditForm
      :key="tableCode"
      @register="registerEditFormModal"
      @success="onEditFormSaveSuccess"
    />
  </div>
</template>
<script lang="ts">
  import { defineComponent, ref, onBeforeMount, onUnmounted, h } from 'vue';
  import { useRouter } from 'vue-router';

  import { BasicTable, useTable, TableAction } from '/@/components/Table';

  import {
    SearchOutlined,
    PlusOutlined,
    EditOutlined,
    DeleteOutlined,
  } from '@ant-design/icons-vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { useModal } from '/@/components/Modal';
  import { QcUnifyTransToChildProps } from '/#/QcUnify';
  import { OperationTypeEnum } from '/@/enums/appEnum';
  import { FormSchema } from '/@/components/Form';
  import { BasicColumn } from '/@/components/Table';
  import CrudEditForm from './Edit.vue';

  import { useMessage } from '/@/hooks/web/useMessage';

  import {
    getQueryCondition,
    queryData,
    getFormSchema,
    deleteData,
  } from '/@/api/platform/dbtableData';
  import {
    DBTableDataQueryConditionDto,
    DBTableDataEditFormDto,
    DBTableDataOperateDto,
  } from '/@/api/platform/model/dbtableDataModel';
  import { DBTableColumnDto } from '/@/api/platform/model/dbtableColumnModel';

  import {
    getFormSchemaByConditionFormItem,
    getBasicColumnByColumnDto,
    getFormSchemaByColumn,
  } from '/@/utils/schemaUtil';

  const { createErrorModal, createMessage } = useMessage();
  const [registerEditFormModal, { openModal: openEditFormModal }] = useModal();

  export default defineComponent({
    name: 'CommonCrudIndex',
    components: {
      SearchOutlined,
      PlusOutlined,
      EditOutlined,
      DeleteOutlined,
      BasicTable,
      TableAction,
      CrudEditForm,
    },
    //要再setup函数中获取或使用props，需要在setup函数中获取props对象
    setup() {
      const router = useRouter();
      const { t } = useI18n();

      /**
       * 当前模块的数据库表编码
       */
      const tableCode = ref<String | undefined>();
      /**
       * 当前模块的查询条件表单结构
       */
      const queryConditionFormSchemas = ref<FormSchema[]>([]);
      /**
       * 当前模块的显示数据的表格标题
       */
      const moduleTitle = ref<string>('数据表格');
      /**
       * 当前模块的显示数据的表格列集合
       */
      const tableColumns = ref<BasicColumn[]>([]);
      /**
       * 当前模块的显示数据的数据源
       */
      const tableData = ref([]);

      /**
       * 编辑表单Scheme列集合，获取1次后有数据不再从后台接口获取；由于新增和修改时Schema不同（主键不允许修改）因此需要根据操作转换为Scheme对象
       */
      const editFormSchemas = ref<DBTableColumnDto[]>([]);

      const [registerTable, { reload, getForm, setLoading }] = useTable({
        //在useTable中设置title、columns、dataSource时对变量进行赋值界面中不会更新，直接写在Html中时正常
        // title: moduleTitle.value,
        // columns: tableColumns.value,
        // dataSource: tableData.value,
        formConfig: {
          labelWidth: 100, //设置查询表单中label的宽度
          schemas: queryConditionFormSchemas,
          showResetButton: false, //查询条件部分中是否显示重置按钮
          submitFunc: onQueryButtonClick, //设置查询表单中提交的处理函数
        },
        useSearchForm: true,
        showTableSetting: true,
        bordered: true,
        showIndexColumn: false,
        actionColumn: {
          width: 180,
          title: '操作',
          dataIndex: 'action',
          slots: { customRender: 'action' },
          fixed: 'right', //表格操作列是否固定，不设置时默认固定在右侧
        },
      });

      /**
       * 获取查询条件数据，用于生成查询条件表单
       */
      function initQueryConditionData() {
        //先清空已有对象
        queryConditionFormSchemas.value = [];
        moduleTitle.value = '数据表格';
        tableColumns.value = [];
        tableData.value = [];
        if (!tableCode.value) {
          //如果tableCode无效，不对表格标题、表格列集合、表格数据源进行赋值
          //在获取查询条件表单中无表格标题、列集合信息，在查询数据方法中才有；
        } else {
          //查询后台接口得到查询条件表单数据
          getQueryCondition(tableCode.value)
            .then((res) => {
              if (res != undefined && res != null) {
                if (res.items != undefined && res.items != null && res.items.length > 0x0) {
                  //如果后台接口中的查询条件表单项数据不为空，进行转换后赋值
                  let schemas: FormSchema[] = [];
                  res.items.forEach((item) => {
                    //根据查询条件表单项获取转换对应的FormSchema对象
                    schemas.push(getFormSchemaByConditionFormItem(item));
                  });
                  queryConditionFormSchemas.value = schemas;
                }
              }
            })
            .catch((ex) => {
              console.log('getQueryCondition ex', ex);
            });
        }
        console.log(
          'initQueryConditionData queryConditionFormSchemas',
          queryConditionFormSchemas.value,
        );
      }

      /**
       * 获取编辑表单Scheme集合
       */
      async function getEditFormSchemas() {
        let columns: DBTableColumnDto[] = [];
        //调用后台接口获取编辑表单Schema集合信息
        await getFormSchema(tableCode.value)
          .then((res) => {
            console.log('common-crud Index getEditFormSchemas res', res);
            if (!res) {
              //返回结果为空，进行提示
              createErrorModal({
                title: t('sys.api.errorTip'),
                content:
                  '从后台接口获取[' + tableCode.value + ']的表单Schema信息时返回的对象为空。',
                getContainer: () => document.body,
              });
            } else {
              if (!res.items) {
                //返回结果中的表单项集合信息为空，进行提示
                createErrorModal({
                  title: t('sys.api.errorTip'),
                  content:
                    '从后台接口获取[' +
                    tableCode.value +
                    ']的表单Schema信息时返回的集合为空，可能尚未进行配置。',
                  getContainer: () => document.body,
                });
              } else {
                //有编辑表单项集合信息
                //将数据库表列Dto转换为FormSchema对象；在此处不转换，在对应新增或修改的地方进行转换；
                columns = res.items;
              }
            }
          })
          .catch((ex) => {
            console.log('common-crud Index getEditFormSchemas ex', ex);
          });
        editFormSchemas.value = columns;
      }

      /**
       * 查询按钮点击事件，根据界面中的查询条件进行数据查询
       */
      function onQueryButtonClick() {
        console.log('common-crud Index onQueryButtonClick');
        // 此处使用getForm().validate()校验表单不通过仍然会请求后端接口，需要处理。
        // 校验表单，此处需要获取表单校验结果，校验通过才处理请求查询接口，校验不通过不做处理
        getForm()
          .validate()
          .then((value) => {
            //校验通过
            console.log('value >> ', value);

            // 获取表单值
            const values = getForm().getFieldsValue();
            console.log('common-crud Index onQueryButtonClick values', values);
            // 循环遍历表单对象，处理查询表单中的值
            let items = [];
            for (const key in values) {
              // console.log('key', key);
              console.log('key', values[key]);
              let item = {
                code: key,
                val1: '',
                val2: '',
              };
              if (Array.isArray(values[key])) {
                // console.log('values[key]为数组', values[key].length);
                let val1;
                let val2;
                for (let i = 0; i < values[key].length; i++) {
                  val1 = values[key][0];
                  val2 = values[key][1];
                }
                item.val1 = val1;
                item.val2 = val2;
              } else {
                item.val1 = values[key];
              }
              items.push(item);
            }

            //获取查询条件表单中的值，构造查询条件数据对象
            let condition: DBTableDataQueryConditionDto = {
              tablecode: tableCode.value,
              items: items,
            };
            //查询前设置表格状态为加载中
            setLoading(true);
            //查询前清空原有表格列和数据信息
            tableColumns.value = [];
            tableData.value = [];
            //从后台接口查询数据
            queryData(condition)
              .then((res) => {
                console.log('common-crud Index onQueryButtonClick res', res);
                if (res != undefined && res != null) {
                  //获取表格名称--作为显示表格标题
                  if (res.table != undefined && res.table != null) {
                    moduleTitle.value = res.table.name;
                  }
                  //获取表格列集合
                  if (res.columns != undefined && res.columns != null && res.columns.length > 0x0) {
                    //将数据库表列Dto转换为表格的BasicColumn
                    let columns: BasicColumn[] = [];
                    res.columns.forEach((columnDto) => {
                      //根据查询条件表单项获取转换对应的FormSchema对象
                      columns.push(getBasicColumnByColumnDto(columnDto));
                    });
                    tableColumns.value = columns;
                  }
                  //获取表格数据
                  if (res.data != undefined && res.data != null && res.data.length > 0x0) {
                    //如果要映射表格显示列信息可以在此处理：如根据对象ID显示对象名称、根据状态代码显示对应名称
                    tableData.value = res.data;
                  }
                }
              })
              .catch((ex) => {
                console.log('common-crud Index onQueryButtonClick ex', ex);
              });
            //查询完成后修改表格加载状态
            setLoading(false);
          })
          .catch((err) => {
            //校验不通过,需要写出catch，否则控制台会直接输出异常。
            console.log('err >> ', err);
          });
      }

      /**
       * 新增数据按钮点击事件，打开新增数据Modal
       */
      function onAddButtonClick() {
        // console.log('onAddButtonClick');
        openCrudEditFormModal(OperationTypeEnum.ADD, null, null);
      }

      /**
       * 修改数据按钮点击事件，打开修改数据Modal
       */
      function onEditButtonClick(record: Recordable) {
        // console.log('onEditButtonClick', record);
        openCrudEditFormModal(OperationTypeEnum.EDIT, null, record);
      }

      /**
       * 删除数据按钮点击事件
       */
      function onDeleteButtonClick(record: Recordable) {
        //构造删除传入数据，将行信息均传入，可能主键是多个组合
        let dto: DBTableDataOperateDto = {
          tablecode: tableCode.value,
          data: record, //表格行数据
        };
        deleteData(dto)
          .then((res) => {
            console.log('common-crud Index.vue onDeleteButtonClick deleteData res', res);
            if (!res || Object.keys(res).length == 0) {
              createMessage.success('删除数据成功。', 2);
              //刷新数据
              onQueryButtonClick();
            } else {
              //显示提示信息
              createMessage.error(res, 5);
            }
          })
          .catch((ex) => {
            console.log('common-crud Index.vue onDeleteButtonClick deleteData ex', ex);
          });
      }

      /**
       * 打开通用的CRUD表单编辑Modal
       */
      async function openCrudEditFormModal(
        operateType: OperationTypeEnum,
        dataId: number | String | undefined,
        data: any | undefined,
      ) {
        //如果编辑表单schemas集合为空调用1次获取接口
        if (!editFormSchemas.value || editFormSchemas.value.length < 0x1) {
          await getEditFormSchemas();
        }

        //根据操作类型，将数据库表列Dto转换为表单Schema对象
        let isAddOperate = operateType === OperationTypeEnum.ADD ? true : false;
        let schemas: FormSchema[] = [];
        editFormSchemas.value.forEach((columnDto) => {
          //根据查询条件表单项获取转换对应的FormSchema对象
          schemas.push(getFormSchemaByColumn(columnDto, isAddOperate));
        });
        console.log('openCrudEditFormModal editFormSchemas', schemas);

        //构造父组件给子组件传值对象
        let propsData: QcUnifyTransToChildProps = {
          moduleName: moduleTitle.value,
          operateType: OperationTypeEnum.ADD,
          formSchemas: schemas, //传编辑表单Scheme
          tableCode: tableCode.value, //传数据库表编码
        };
        //可选传递给子组件的对象：data--数据对象（修改时传入）、api--保存接口地址
        //如果是修改数据，对传值对象中的data进行赋值;
        //传编辑表单中赋值的数据对象，如果是新增不传值
        if (operateType === OperationTypeEnum.EDIT) {
          propsData.operateType = OperationTypeEnum.EDIT;
          //如果指定的对象Id不为空，对传递给子组件中的dataId进行赋值
          if (dataId != undefined && dataId != null && dataId != '') propsData.dataId = dataId;
          propsData.data = data;
        }

        openEditFormModal(true, propsData);
      }

      /**
       * 操作结束后刷新表格数据
       */
      function onEditFormSaveSuccess() {
        onQueryButtonClick();
      }

      onBeforeMount(() => {
        console.log('common-crud Index onBeforeMount');
        //从router.fullPath中获取传入的参数，并对空元素进行去除；直接取最后一个作为动态参数值
        let fullPathArray = router.currentRoute.value.fullPath.split('/');
        if (fullPathArray != undefined && fullPathArray != null && fullPathArray.length > 0x0) {
          //去除空格和空白元素
          let notEmptyPathArray = fullPathArray.filter((str) => str.length > 0x0);
          if (
            notEmptyPathArray != undefined &&
            notEmptyPathArray != null &&
            notEmptyPathArray.length > 0x0
          ) {
            tableCode.value = notEmptyPathArray[notEmptyPathArray.length - 1];
          }
        }
        initQueryConditionData();
      });
      onUnmounted(() => {
        console.log('common-crud Index.vue onUnmounted');
      });

      return {
        tableCode,
        queryConditionFormSchemas,
        moduleTitle,
        tableColumns,
        tableData,
        registerTable,
        editFormSchemas,
        initQueryConditionData,
        onQueryButtonClick,
        onAddButtonClick,
        onEditButtonClick,
        onDeleteButtonClick,
        onEditFormSaveSuccess,
        registerEditFormModal,
      };
    },
  });
</script>
<style scoped lang="less"></style>
